package com.miaoshaproject.log;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;

/**
 * @Description
 * @Author wuqiusheng
 * @Version 1.0
 * @Date 2025/6/4 20:36
 */
@Aspect
@Component
public class OperationLogAspect {
    // 注入所有SPI扩展实现，通过 META-INF/spring.factories 文件声明 SPI 实现类，Spring Boot 启动时自动加载并注入所有实现类。
    @Autowired
    private List<OperationTypeProvider> typeProviders;

    /**​ 解析操作类型描述 */
    private String resolveOperationType(String typeCode) {
        // 根据type找到map对应的value
        return typeProviders.stream()
                .map(provider -> provider.provideOperationTypes().get(typeCode))
                .filter(Objects::nonNull)
                .findFirst()
                .orElse("未知操作");
    }

    /**​ 环绕通知记录日志 */
    @Around("@annotation(operationLog)")
    public Object logOperation(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取名称
        String methodName = signature.getName();
        String module = operationLog.module();
        String typeDesc = resolveOperationType(operationLog.type()); // SPI扩展解析类型

        // 业务ID
        String bizId = operationLog.bizId();

        long startTime = System.currentTimeMillis();
        Object result;
        try {
            result = joinPoint.proceed(); // 执行原方法
            long costTime = System.currentTimeMillis() - startTime;
            // 日志持久化（示例）
            saveLog(module, typeDesc, bizId, methodName, costTime, null);
            return result;
        } catch (Exception e) {
            saveLog(module, typeDesc, bizId, methodName, 0, e.getMessage());
            throw e;
        }
    }

    /**​ 日志持久化（可扩展为数据库存储） */
    private void saveLog(String module, String typeDesc, String bizId, String method, long costTime, String error) {
        System.out.printf("[操作日志] 模块:%s | 类型:%s | 业务ID:%s | 方法:%s | 耗时:%dms | 错误:%s%n",
                module, typeDesc, bizId, method, costTime, error);
    }
}
